package com.smasher.core.encrypt.unsymmetric;


import android.util.Base64;
import android.util.Log;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;

/**
 * RSA 工具类
 */
public class RSAUtil {

    public static final String TAG = "RSAUtil";

    private static final String ALGORITHM = "RSA";
    private static final String CIPHER_TRANSFORMATION = "RSA/ECB/PKCS1Padding";
    private static final String SIGNATURE_ALGORITHM = "SHA256withRSA";
    private static final int KEY_SIZE = 2048; // 推荐使用 2048 位或更高

    /**
     * 生成 RSA 密钥对。
     *
     * @return Base64 编码的公钥和私钥字符串
     */
    public static KeyPair generateKeyPair() {
        try {
            KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
            keyGen.initialize(KEY_SIZE);
            return keyGen.generateKeyPair();
        } catch (Exception e) {
            Log.e(TAG, "generateKeyPair: ", e);
        }
        return null;
    }

    /**
     * 生成 RSA 密钥对。
     *
     * @return 包含 Base64 编码的公钥和私钥字符串的 Map
     */
    public static Map<String, String> generateMapByKeyPair(KeyPair keyPair) {
        try {
            // 将公钥和私钥编码为 Base64 字符串
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();

            byte[] publicKeyBytes = publicKey.getEncoded();
            byte[] privateKeyBytes = privateKey.getEncoded();

            String publicKeyBase64 = Base64.encodeToString(publicKeyBytes, Base64.DEFAULT);
            String privateKeyBase64 = Base64.encodeToString(privateKeyBytes, Base64.DEFAULT);

            // 返回一个包含 Base64 编码公钥和私钥的 Map
            Map<String, String> keyPairMap = new HashMap<>();
            keyPairMap.put("publicKey", publicKeyBase64);
            keyPairMap.put("privateKey", privateKeyBase64);

            return keyPairMap;
        } catch (Exception e) {
            Log.e(TAG, "generateKeyPair: ", e);
        }
        return null;
    }

    /**
     * 使用公钥进行 RSA 加密。
     *
     * @param data         待加密的数据字符串
     * @param publicKeyStr Base64 编码的公钥字符串
     * @return Base64 编码的加密数据字符串
     */
    public static String encrypt(String data, String publicKeyStr) {
        try {
            PublicKey publicKey = getPublicKey(publicKeyStr);
            Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);

            byte[] encryptedData = cipher.doFinal(data.getBytes());
            return Base64.encodeToString(encryptedData, Base64.DEFAULT);
        } catch (Exception e) {
            Log.e(TAG, "encrypt: ", e);
        }
        return null;
    }

    /**
     * 使用私钥进行 RSA 解密。
     *
     * @param encryptedData Base64 编码的加密数据字符串
     * @param privateKeyStr Base64 编码的私钥字符串
     * @return 解密后的数据字符串
     */
    public static String decrypt(String encryptedData, String privateKeyStr) {
        try {
            PrivateKey privateKey = getPrivateKey(privateKeyStr);
            Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);

            byte[] decodedData = Base64.decode(encryptedData, Base64.DEFAULT);
            byte[] decryptedData = cipher.doFinal(decodedData);
            return new String(decryptedData);
        } catch (Exception e) {
            Log.e(TAG, "decrypt: ", e);
        }
        return null;
    }

    /**
     * 使用私钥生成数字签名。
     *
     * @param data          待签名的数据字符串
     * @param privateKeyStr Base64 编码的私钥字符串
     * @return Base64 编码的签名字符串
     */
    public static String sign(String data, String privateKeyStr) {
        try {
            PrivateKey privateKey = getPrivateKey(privateKeyStr);
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initSign(privateKey);
            signature.update(data.getBytes());

            byte[] signBytes = signature.sign();
            return Base64.encodeToString(signBytes, Base64.DEFAULT);
        } catch (Exception e) {
            Log.e(TAG, "sign: ", e);
        }
        return null;
    }

    /**
     * 使用公钥验证数字签名。
     *
     * @param data         原始数据字符串
     * @param publicKeyStr Base64 编码的公钥字符串
     * @param signStr      Base64 编码的签名字符串
     * @return 验证结果（true 表示成功，false 表示失败）
     */
    public static boolean verify(String data, String publicKeyStr, String signStr) {
        try {
            PublicKey publicKey = getPublicKey(publicKeyStr);
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initVerify(publicKey);
            signature.update(data.getBytes());

            byte[] signBytes = Base64.decode(signStr, Base64.DEFAULT);
            return signature.verify(signBytes);
        } catch (Exception e) {
            Log.e(TAG, "verify: ", e);
        }
        return false;
    }

    /**
     * 将 Base64 编码的公钥字符串转换为 PublicKey 对象。
     *
     * @param publicKeyStr Base64 编码的公钥字符串
     * @return PublicKey 对象
     */
    private static PublicKey getPublicKey(String publicKeyStr) throws Exception {
        byte[] keyBytes = Base64.decode(publicKeyStr, Base64.DEFAULT);
        X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        return keyFactory.generatePublic(spec);
    }

    /**
     * 将 Base64 编码的私钥字符串转换为 PrivateKey 对象。
     *
     * @param privateKeyStr Base64 编码的私钥字符串
     * @return PrivateKey 对象
     */
    private static PrivateKey getPrivateKey(String privateKeyStr) throws Exception {
        byte[] keyBytes = Base64.decode(privateKeyStr, Base64.DEFAULT);
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        return keyFactory.generatePrivate(spec);
    }
}
